package com.tom.demo.service.common.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.CharsetUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.ZipUtil;
import com.tom.demo.common.entity.CpTempFileBaseInfo;
import com.tom.demo.common.utils.ThreadPoolFactoryManage;
import com.tom.demo.service.common.AnalyzeSplitGenerateService;
import io.minio.MinioClient;
import io.minio.PutObjectArgs;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FilenameUtils;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class AnalyzeSplitGenerateConcurrentServiceImpl implements AnalyzeSplitGenerateService {
    @Resource
    private MinioClient minioClient;

    @Value("${bucketName}")
    private String minioBucket;

    @Value("${temp.dir}")
    private String tempDir;

    @Resource(name = "executorService")
    private ExecutorService executorService;

    private static final Set<String> ALLOWED_EXTENSIONS = new HashSet<>(
            Arrays.asList("pdf", "xls", "xlsx", "csv", "zip"));

    /**
     * 文件上传接口 - 使用并发处理
     */
    @Override
    public List<CpTempFileBaseInfo> analyzeSplitGenerateService(MultipartFile[] files, HttpServletRequest httpServletRequest) {
        // 使用线程安全的集合
        ConcurrentLinkedQueue<CpTempFileBaseInfo> concurrentResults = new ConcurrentLinkedQueue<>();
        List<CompletableFuture<Void>> futures = new ArrayList<>();

        // 为每个文件创建异步处理任务
        for (MultipartFile file : files) {
            CompletableFuture<Void> future = CompletableFuture
                    .runAsync(() -> {
                        List<CpTempFileBaseInfo> fileResults = processFileAsync(file);
                        concurrentResults.addAll(fileResults);
                    }, executorService)
                    .exceptionally(throwable -> {
                        log.error("处理文件异常: {}", file.getOriginalFilename(), throwable);
                        CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
                        failInfo.setFileName(file.getOriginalFilename());
                        failInfo.setParseStatus(1);
                        failInfo.setFailReason("处理文件时发生错误: " + throwable.getMessage());
                        concurrentResults.add(failInfo);
                        return null;
                    });
            futures.add(future);
        }

        // 等待所有任务完成
        try {
            CompletableFuture<Void> allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[0]));
            allOf.get(5, TimeUnit.MINUTES); // 设置超时时间
        } catch (Exception e) {
            log.error("并发处理文件时发生异常", e);
            // 取消未完成的任务
            futures.forEach(future -> {
                if (!future.isDone()) {
                    future.cancel(true);
                }
            });
        }

        // 转换为List返回
        return new ArrayList<>(concurrentResults);
    }

    /**
     * 异步处理单个文件
     */
    private List<CpTempFileBaseInfo> processFileAsync(MultipartFile file) {
        // 使用线程安全的集合
        ConcurrentLinkedQueue<CpTempFileBaseInfo> results = new ConcurrentLinkedQueue<>();

        try {
            if (file.isEmpty()) {
                return new ArrayList<>(results);
            }

            String originalFilename = file.getOriginalFilename();
            if (originalFilename == null || originalFilename.isEmpty()) {
                return new ArrayList<>(results);
            }

            String extension = FilenameUtils.getExtension(originalFilename).toLowerCase();

            if (!ALLOWED_EXTENSIONS.contains(extension)) {
                CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
                failInfo.setFileName(originalFilename);
                failInfo.setParseStatus(1);
                failInfo.setFailReason("不支持的文件格式: " + extension);
                results.add(failInfo);
                return new ArrayList<>(results);
            }

            CpTempFileBaseInfo fileInfo = new CpTempFileBaseInfo();
            fileInfo.setFileName(originalFilename);
            fileInfo.setFundId(123);
            fileInfo.setFundCode("PF123456");
            fileInfo.setCustodyReview("4");

            processFileWithConcurrency(file, fileInfo, results);

        } catch (Exception e) {
            log.error("处理文件异常: {}", file.getOriginalFilename(), e);
            CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
            failInfo.setFileName(file.getOriginalFilename());
            failInfo.setParseStatus(1);
            failInfo.setFailReason("处理文件时发生错误: " + e.getMessage());
            results.add(failInfo);
        }

        return new ArrayList<>(results);
    }

    /**
     * 并发处理单个文件
     */
    private void processFileWithConcurrency(MultipartFile file, CpTempFileBaseInfo fileInfo,
                                            ConcurrentLinkedQueue<CpTempFileBaseInfo> results) throws Exception {
        String originalFilename = file.getOriginalFilename();
        String extension = Objects.requireNonNull(FilenameUtils.getExtension(originalFilename)).toLowerCase();
        fileInfo.setFileType(getFileTypeCode(extension));
        fileInfo.setDataRoute(null);

        if ("zip".equalsIgnoreCase(extension)) {
            processZipFileAsync(file, fileInfo.getFundId(), fileInfo.getFundCode(),
                    fileInfo.getCustodyReview(), FilenameUtils.getBaseName(originalFilename), results);
        } else if ("xls".equalsIgnoreCase(extension) || "xlsx".equalsIgnoreCase(extension)) {
            processExcelSheetsAsync(file.getInputStream(), fileInfo, results);
        } else if ("csv".equalsIgnoreCase(extension)) {
            processCsvFileAsync(file.getInputStream(), fileInfo, results);
        } else if ("pdf".equalsIgnoreCase(extension)) {
            // PDF异步上传
            CompletableFuture<Void> uploadFuture = CompletableFuture.runAsync(() -> {
                try {
                    String objectName = generateUniqueObjectName(file.getOriginalFilename());
                    uploadToMinio(file.getInputStream(), objectName, file.getContentType(), file.getSize());
                    fileInfo.setFilePath(getMinioFilePath(objectName));
                    fileInfo.setParseStatus(0);
                } catch (Exception e) {
                    fileInfo.setParseStatus(1);
                    fileInfo.setFailReason("PDF上传失败: " + e.getMessage());
                    log.error("PDF上传失败", e);
                }
            }, ThreadPoolFactoryManage.getWaferCheckExecutor());

            // 等待上传完成
            uploadFuture.get();
            results.add(fileInfo);
        }
    }

    /**
     * 异步处理ZIP文件
     */
    private void processZipFileAsync(MultipartFile file, Integer fundId, String fundCode,
                                     String custodyReview, String zipBaseName,
                                     ConcurrentLinkedQueue<CpTempFileBaseInfo> results) throws Exception {
        Path tempPath = Paths.get(tempDir, IdUtil.simpleUUID());
        Files.createDirectories(tempPath);

        try {
            extractZipFileAsync(file.getInputStream(), tempPath, zipBaseName,
                    fundId, fundCode, custodyReview, results);
        } catch (Exception e) {
            CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
            failInfo.setFileName(file.getOriginalFilename());
            failInfo.setParseStatus(1);
            failInfo.setFailReason("ZIP文件格式错误: " + e.getMessage());
            results.add(failInfo);
            log.error("zip文件解压异常", e);
        } finally {
            deleteDirectory(tempPath.toFile());
        }
    }

    /**
     * 异步解压ZIP文件
     */
    private void extractZipFileAsync(InputStream inputStream, Path outputPath, String zipBaseName,
                                     Integer fundId, String fundCode, String custodyReview,
                                     ConcurrentLinkedQueue<CpTempFileBaseInfo> results) throws Exception {
        extractZipFileWithDepthAsync(inputStream, outputPath, zipBaseName, fundId, fundCode,
                custodyReview, results, CharsetUtil.CHARSET_GBK, 0);
    }

    /**
     * 带并发的ZIP解压处理
     */
    private void extractZipFileWithDepthAsync(InputStream inputStream, Path outputPath, String zipBaseName,
                                              Integer fundId, String fundCode, String custodyReview,
                                              ConcurrentLinkedQueue<CpTempFileBaseInfo> results, Charset charset, int depth) throws Exception {
        final int MAX_DEPTH = 10;
        if (depth > MAX_DEPTH) {
            CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
            failInfo.setFileName(zipBaseName);
            failInfo.setDataRoute(zipBaseName);
            failInfo.setParseStatus(1);
            failInfo.setFailReason("ZIP嵌套层级过深，超过最大限制" + MAX_DEPTH + "层");
            results.add(failInfo);
            return;
        }

        String uniqueSubDir = UUID.randomUUID().toString();
        Path zipOutputPath = outputPath.resolve(uniqueSubDir);
        Files.createDirectories(zipOutputPath);

        File tempZipFile = FileUtil.createTempFile("temp_zip", ".zip", true);
        try {
            FileUtil.writeFromStream(inputStream, tempZipFile);

            boolean success = false;
            Exception lastException = null;

            try {
                ZipUtil.unzip(tempZipFile, zipOutputPath.toFile(), charset);
                success = true;
            } catch (Exception e) {
                lastException = e;
                log.error("使用指定编码{}解压失败，尝试其他编码", charset, e);
            }

            if (!success) {
                Charset[] charsets = new Charset[]{
                        CharsetUtil.CHARSET_UTF_8,
                        CharsetUtil.CHARSET_GBK,
                        CharsetUtil.CHARSET_ISO_8859_1
                };

                for (Charset cs : charsets) {
                    if (cs.equals(charset)) continue;

                    try {
                        ZipUtil.unzip(tempZipFile, zipOutputPath.toFile(), cs);
                        log.info("成功使用{}编码解压文件", cs);
                        success = true;
                        charset = cs;
                        break;
                    } catch (Exception e) {
                        log.error("尝试使用{}编码解压失败", cs, e);
                    }
                }
            }

            if (!success) {
                throw new Exception("无法解压ZIP文件，尝试了多种编码都失败", lastException);
            }

            // 并发处理解压后的文件
            processExtractedFilesWithConcurrency(zipOutputPath.toFile(), outputPath, zipBaseName,
                    fundId, fundCode, custodyReview, results, charset, depth);
        } finally {
            FileUtil.del(tempZipFile);
        }
    }

    /**
     * 并发处理解压后的文件
     */
    private void processExtractedFilesWithConcurrency(File directory, Path outputPath, String zipBaseName,
                                                      Integer fundId, String fundCode, String custodyReview,
                                                      ConcurrentLinkedQueue<CpTempFileBaseInfo> results,
                                                      Charset charset, int depth) throws Exception {
        File[] files = directory.listFiles();
        if (files == null) return;

        List<CompletableFuture<Void>> fileFutures = new ArrayList<>();

        for (File file : files) {
            CompletableFuture<Void> fileFuture = CompletableFuture.runAsync(() -> {
                try {
                    processExtractedFile(file, outputPath, zipBaseName, fundId, fundCode,
                            custodyReview, results, charset, depth);
                } catch (Exception e) {
                    log.error("处理解压文件异常: {}", file.getName(), e);
                }
            }, executorService);

            fileFutures.add(fileFuture);
        }

        // 等待所有文件处理完成
        CompletableFuture.allOf(fileFutures.toArray(new CompletableFuture[0])).get();
        FileUtil.del(directory);
    }

    /**
     * 处理单个解压文件
     */
    private void processExtractedFile(File file, Path outputPath, String zipBaseName,
                                      Integer fundId, String fundCode, String custodyReview,
                                      ConcurrentLinkedQueue<CpTempFileBaseInfo> results,
                                      Charset charset, int depth) throws Exception {
        String fileName = file.getName();
        String currentRelativePath;

        if (StrUtil.isEmpty(zipBaseName)) {
            currentRelativePath = fileName;
        } else {
            currentRelativePath = zipBaseName + "/" + fileName;
        }

        if (file.isDirectory()) {
            processExtractedFilesWithConcurrency(file, outputPath, currentRelativePath,
                    fundId, fundCode, custodyReview, results, charset, depth);
        } else {
            String fileExtension = FileUtil.extName(fileName).toLowerCase();
            Path filePath = file.toPath();

            if ("zip".equalsIgnoreCase(fileExtension)) {
                try (InputStream fileIn = Files.newInputStream(filePath)) {
                    extractZipFileWithDepthAsync(fileIn, outputPath, currentRelativePath,
                            fundId, fundCode, custodyReview, results, charset, depth + 1);
                }
            } else if (ALLOWED_EXTENSIONS.contains(fileExtension)) {
                processValidFile(file, currentRelativePath, fundId, fundCode, custodyReview, results, fileExtension);
            } else {
                CpTempFileBaseInfo failInfo = new CpTempFileBaseInfo();
                failInfo.setFileName(fileName);
                failInfo.setDataRoute(currentRelativePath);
                failInfo.setParseStatus(1);
                failInfo.setFailReason("不支持的文件格式: " + fileExtension);
                results.add(failInfo); // 直接添加到线程安全的队列
            }
        }
    }

    /**
     * 处理有效文件
     */
    private void processValidFile(File file, String currentRelativePath, Integer fundId,
                                  String fundCode, String custodyReview,
                                  ConcurrentLinkedQueue<CpTempFileBaseInfo> results,
                                  String fileExtension) throws Exception {
        CpTempFileBaseInfo fileInfo = new CpTempFileBaseInfo();
        fileInfo.setFileName(file.getName());
        fileInfo.setFundId(fundId);
        fileInfo.setFundCode(fundCode);
        fileInfo.setCustodyReview(custodyReview);
        fileInfo.setDataRoute(currentRelativePath);
        fileInfo.setFileType(getFileTypeCode(fileExtension));

        try {
            if ("xls".equalsIgnoreCase(fileExtension) || "xlsx".equalsIgnoreCase(fileExtension)) {
                ConcurrentLinkedQueue<CpTempFileBaseInfo> excelResults = new ConcurrentLinkedQueue<>();
                processExcelSheetsAsync(Files.newInputStream(file.toPath()), fileInfo, excelResults);
                results.addAll(excelResults);
            } else if ("csv".equalsIgnoreCase(fileExtension)) {
                ConcurrentLinkedQueue<CpTempFileBaseInfo> csvResults = new ConcurrentLinkedQueue<>();
                processCsvFileAsync(Files.newInputStream(file.toPath()), fileInfo, csvResults);
                results.addAll(csvResults);
            } else if ("pdf".equalsIgnoreCase(fileExtension)) {
                // 异步上传PDF
                CompletableFuture.runAsync(() -> {
                    try {
                        String objectName = generateUniqueObjectName(fileInfo.getFileName());
                        uploadToMinio(Files.newInputStream(file.toPath()), objectName,
                                getContentType(fileExtension), Files.size(file.toPath()));
                        fileInfo.setFilePath(getMinioFilePath(objectName));
                        fileInfo.setParseStatus(0);
                    } catch (Exception e) {
                        fileInfo.setParseStatus(1);
                        fileInfo.setFailReason("PDF上传失败: " + e.getMessage());
                        log.error("PDF上传失败", e);
                    }
                }, ThreadPoolFactoryManage.getWaferCheckExecutor()).get(); // 等待上传完成

                results.add(fileInfo);
            }
        } catch (Exception e) {
            fileInfo.setParseStatus(1);
            fileInfo.setFailReason("处理文件失败: " + e.getMessage());
            results.add(fileInfo);
        }
    }

    /**
     * 异步处理Excel文件的每个工作表
     */
    private void processExcelSheetsAsync(InputStream inputStream, CpTempFileBaseInfo baseFileInfo,
                                         ConcurrentLinkedQueue<CpTempFileBaseInfo> results) throws IOException {
        Path tempExcelPath = Files.createTempFile("excel_", ".xlsx");
        Files.copy(inputStream, tempExcelPath, StandardCopyOption.REPLACE_EXISTING);

        try (Workbook workbook = WorkbookFactory.create(Files.newInputStream(tempExcelPath))) {
            List<CompletableFuture<CpTempFileBaseInfo>> sheetFutures = new ArrayList<>();

            // 为每个sheet创建异步处理任务
            for (int i = 0; i < workbook.getNumberOfSheets(); i++) {
                final int sheetIndex = i;
                CompletableFuture<CpTempFileBaseInfo> sheetFuture = CompletableFuture.supplyAsync(() -> {
                    try {
                        return processExcelSheet(tempExcelPath, sheetIndex, baseFileInfo);
                    } catch (Exception e) {
                        log.error("处理Excel Sheet异常", e);
                        return null;
                    }
                }, executorService);

                sheetFutures.add(sheetFuture);
            }

            // 等待所有sheet处理完成
            CompletableFuture<Void> allSheets = CompletableFuture.allOf(
                    sheetFutures.toArray(new CompletableFuture[0]));

            allSheets.get();

            boolean foundAnyContent = false;
            for (CompletableFuture<CpTempFileBaseInfo> future : sheetFutures) {
                CpTempFileBaseInfo result = future.get();
                if (result != null) {
                    results.add(result);
                    foundAnyContent = true;
                }
            }

            if (!foundAnyContent) {
                baseFileInfo.setParseStatus(1);
                baseFileInfo.setFailReason("Excel文件的所有sheet页都没有内容");
                results.add(baseFileInfo);
            }

        } catch (Exception e) {
            baseFileInfo.setParseStatus(1);
            baseFileInfo.setFailReason("excel文件损坏，无法读取");
            results.add(baseFileInfo);
        } finally {
            Files.deleteIfExists(tempExcelPath);
        }
    }

    /**
     * 异步处理CSV文件
     */
    private void processCsvFileAsync(InputStream inputStream, CpTempFileBaseInfo baseFileInfo,
                                     ConcurrentLinkedQueue<CpTempFileBaseInfo> results) throws Exception {
        Path tempCsvPath = Files.createTempFile("csv_", ".csv");
        Files.copy(inputStream, tempCsvPath, StandardCopyOption.REPLACE_EXISTING);

        CompletableFuture<Void> processFuture = CompletableFuture.runAsync(() -> {
            try {
                boolean hasContent = false;

                try (InputStream fis = Files.newInputStream(tempCsvPath);
                     InputStreamReader isr = new InputStreamReader(fis, StandardCharsets.ISO_8859_1);
                     BufferedReader reader = new BufferedReader(isr)) {

                    String line;
                    while ((line = reader.readLine()) != null) {
                        String trimmedLine = line.trim();
                        if (!trimmedLine.isEmpty()) {
                            String contentWithoutSeparators = trimmedLine.replace(",", "")
                                    .replace(";", "")
                                    .replace("|", "")
                                    .replace("\t", "");
                            if (!contentWithoutSeparators.isEmpty()) {
                                hasContent = true;
                                break;
                            }
                        }
                    }
                }

                if (hasContent) {
                    String originalFilename = baseFileInfo.getFileName();
                    String nameWithoutExt = FilenameUtils.removeExtension(originalFilename);
                    String extension = FilenameUtils.getExtension(originalFilename);
                    String newFileName = nameWithoutExt + "." + extension;

                    // 异步上传CSV
                    String objectName = generateUniqueObjectName(newFileName);
                    try (InputStream csvInputStream = Files.newInputStream(tempCsvPath)) {
                        uploadToMinio(csvInputStream, objectName,
                                getContentType(extension), Files.size(tempCsvPath));
                    }

                    baseFileInfo.setFileName(newFileName);
                    baseFileInfo.setFilePath(getMinioFilePath(objectName));
                    baseFileInfo.setParseStatus(0);
                } else {
                    baseFileInfo.setParseStatus(1);
                    baseFileInfo.setFailReason("CSV文件为空或只包含分隔符");
                }

                results.add(baseFileInfo); // 直接添加到线程安全的队列

            } catch (Exception e) {
                baseFileInfo.setParseStatus(1);
                baseFileInfo.setFailReason("解析CSV文件失败: " + e.getMessage());
                results.add(baseFileInfo);
                log.error("解析CSV文件失败", e);
            } finally {
                try {
                    Files.deleteIfExists(tempCsvPath);
                } catch (Exception e) {
                    log.error("删除临时CSV文件失败", e);
                }
            }
        }, executorService);

        processFuture.get(); // 等待处理完成
    }

    // processExcelSheet 方法保持不变
    private CpTempFileBaseInfo processExcelSheet(Path tempExcelPath, int sheetIndex,
                                                 CpTempFileBaseInfo baseFileInfo) throws Exception {
        try (Workbook workbook = WorkbookFactory.create(Files.newInputStream(tempExcelPath))) {
            Sheet sheet = workbook.getSheetAt(sheetIndex);
            String sheetName = sheet.getSheetName();

            if (!checkSheetContent(sheet)) {
                return null;
            }

            CpTempFileBaseInfo sheetFileInfo = new CpTempFileBaseInfo();
            sheetFileInfo.setFundId(baseFileInfo.getFundId());
            sheetFileInfo.setFundCode(baseFileInfo.getFundCode());
            sheetFileInfo.setCustodyReview(baseFileInfo.getCustodyReview());
            sheetFileInfo.setFileType(baseFileInfo.getFileType());
            sheetFileInfo.setDataRoute(baseFileInfo.getDataRoute());

            String originalFilename = baseFileInfo.getFileName();
            String nameWithoutExt = FilenameUtils.removeExtension(originalFilename);
            String extension = FilenameUtils.getExtension(originalFilename);
            String newFileName = nameWithoutExt + "_" + sheetName + "." + extension;
            sheetFileInfo.setFileName(newFileName);

            Workbook singleSheetWorkbook;
            if (workbook instanceof XSSFWorkbook) {
                singleSheetWorkbook = new XSSFWorkbook();
            } else {
                singleSheetWorkbook = new HSSFWorkbook();
            }

            Sheet newSheet = singleSheetWorkbook.createSheet(sheetName);
            copySheet(sheet, newSheet);

            Path tempSheetPath = Files.createTempFile("sheet_", "." + extension);
            try (FileOutputStream out = new FileOutputStream(tempSheetPath.toFile())) {
                singleSheetWorkbook.write(out);
            }
            singleSheetWorkbook.close();

            String objectName = generateUniqueObjectName(newFileName);
            CompletableFuture<Void> uploadFuture = CompletableFuture.runAsync(() -> {
                try (InputStream sheetInputStream = Files.newInputStream(tempSheetPath)) {
                    uploadToMinio(sheetInputStream, objectName,
                            getContentType(extension), Files.size(tempSheetPath));
                } catch (Exception e) {
                    log.error("上传单sheet文件到MinIO出错", e);
                    throw new RuntimeException(e);
                }
            }, ThreadPoolFactoryManage.getWaferCheckExecutor());

            uploadFuture.get();
            Files.deleteIfExists(tempSheetPath);

            sheetFileInfo.setFilePath(getMinioFilePath(objectName));
            sheetFileInfo.setParseStatus(0);
            return sheetFileInfo;
        }
    }
    /**
     * 复制sheet内容
     * @param sourceSheet 源sheet
     * @param targetSheet 目标sheet
     */
    private void copySheet(Sheet sourceSheet, Sheet targetSheet) {
        // 复制行
        for (int i = sourceSheet.getFirstRowNum(); i <= sourceSheet.getLastRowNum(); i++) {
            Row sourceRow = sourceSheet.getRow(i);
            if (sourceRow != null) {
                Row targetRow = targetSheet.createRow(i);

                // 复制行高和样式
                targetRow.setHeight(sourceRow.getHeight());

                // 复制单元格
                for (int j = sourceRow.getFirstCellNum(); j < sourceRow.getLastCellNum(); j++) {
                    Cell sourceCell = sourceRow.getCell(j);
                    if (sourceCell != null) {
                        Cell targetCell = targetRow.createCell(j);

                        // 复制单元格内容
                        switch (sourceCell.getCellType()) {
                            case STRING:
                                targetCell.setCellValue(sourceCell.getStringCellValue());
                                break;
                            case NUMERIC:
                                if (DateUtil.isCellDateFormatted(sourceCell)) {
                                    targetCell.setCellValue(sourceCell.getDateCellValue());
                                    // 创建新样式而不是直接克隆
                                    CellStyle dateStyle = targetCell.getSheet().getWorkbook().createCellStyle();
                                    // 复制日期格式
                                    short formatIndex = sourceCell.getCellStyle().getDataFormat();
                                    String formatString = sourceCell.getCellStyle().getDataFormatString();
                                    if (formatString != null) {
                                        dateStyle.setDataFormat(targetCell.getSheet().getWorkbook().createDataFormat().getFormat(formatString));
                                    } else {
                                        dateStyle.setDataFormat(formatIndex);
                                    }
                                    targetCell.setCellStyle(dateStyle);
                                } else {
                                    targetCell.setCellValue(sourceCell.getNumericCellValue());
                                }
                                break;
                            case BOOLEAN:
                                targetCell.setCellValue(sourceCell.getBooleanCellValue());
                                break;
                            case FORMULA:
                                targetCell.setCellFormula(sourceCell.getCellFormula());
                                break;
                            case BLANK:
                                targetCell.setBlank();
                                break;
                            default:
                                break;
                        }
                    }
                }
            }
        }
    }
    /**
     * 检查工作表是否有内容
     * @param sheet 工作表对象
     * @return 是否有内容
     */
    private boolean checkSheetContent(Sheet sheet) {
        int firstRow = sheet.getFirstRowNum();
        int lastRow = sheet.getLastRowNum();

        // 检查sheet是否有任何行
        if (lastRow >= firstRow) {  // 这意味着至少有一行
            // 遍历所有行
            for (int rowIndex = firstRow; rowIndex <= lastRow; rowIndex++) {
                Row row = sheet.getRow(rowIndex);
                if (row != null) {  // 确保行不是null
                    // 遍历行中的所有单元格
                    for (int cellIndex = row.getFirstCellNum(); cellIndex < row.getLastCellNum(); cellIndex++) {
                        Cell cell = row.getCell(cellIndex);
                        if (cell != null && cell.getCellType() != CellType.BLANK) {
                            String cellValue = getCellValueAsString(cell);
                            if (cellValue != null && !cellValue.trim().isEmpty()) {
                                return true; // 找到了内容
                            }
                        }
                    }
                }
            }
        }

        return false; // 没有找到内容
    }

    /**
     * 获取单元格值为字符串
     * @param cell 单元格对象
     * @return 单元格值字符串
     */
    private String getCellValueAsString(Cell cell) {
        if (cell == null) {
            return null;
        }

        switch (cell.getCellType()) {
            case STRING:
                return cell.getStringCellValue();
            case NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    return cell.getDateCellValue().toString();
                } else {
                    return String.valueOf(cell.getNumericCellValue());
                }
            case BOOLEAN:
                return String.valueOf(cell.getBooleanCellValue());
            case FORMULA:
                try {
                    return cell.getStringCellValue();
                } catch (Exception e) {
                    try {
                        return String.valueOf(cell.getNumericCellValue());
                    } catch (Exception ex) {
                        return cell.getCellFormula();
                    }
                }
            default:
                return "";
        }
    }

    /**
     * 获取文件类型代码
     * @param extension 文件扩展名
     * @return 文件类型代码
     */
    private String getFileTypeCode(String extension) {
        if ("pdf".equalsIgnoreCase(extension)) {
            return "0";
        } else if ("xls".equalsIgnoreCase(extension) || "xlsx".equalsIgnoreCase(extension)) {
            return "1";
        } else if ("jpg".equalsIgnoreCase(extension) || "jpeg".equalsIgnoreCase(extension) ||
                "png".equalsIgnoreCase(extension) || "gif".equalsIgnoreCase(extension)) {
            return "2";
        } else if ("csv".equalsIgnoreCase(extension)) {
            return "3";
        } else {
            return "9"; // 其他类型
        }
    }
    /**
     * 递归删除目录
     * @param directory 要删除的目录
     */
    private void deleteDirectory(File directory) {
        if (directory.exists()) {
            File[] files = directory.listFiles();
            if (files != null) {
                for (File file : files) {
                    if (file.isDirectory()) {
                        deleteDirectory(file);
                    } else {
                        if(file.delete()){
                            log.info("清理临时文件成功！");
                        }

                    }
                }
            }
            if(directory.delete()){
                log.info("清理临时目录成功！");
            }
        }
    }

    /**
     * 生成唯一的对象名
     * @param originalFilename 原始文件名
     * @return 唯一对象名
     */
    private String generateUniqueObjectName(String originalFilename) {
        String extension = FilenameUtils.getExtension(originalFilename);
        String name = FilenameUtils.getBaseName(originalFilename);
        String fileName = (name.length()>60?name.substring(0,60):name);
        if(StringUtils.hasText(fileName)){
            String pattern = "[^a-zA-Z0-9\\u4e00-\\u9fa5-_.]";
            fileName = fileName.replaceAll(pattern, "");
        }
        return fileName + "_" + IdUtil.simpleUUID() + (extension.isEmpty() ? "" : "." + extension);
    }

    /**
     * 上传文件到MinIO
     * @param inputStream 文件输入流
     * @param objectName 对象名称
     * @param contentType 内容类型
     * @param fileSize 文件大小
     * @throws Exception 上传异常
     */
    private void uploadToMinio(InputStream inputStream, String objectName,
                               String contentType, long fileSize) throws Exception {
        minioClient.putObject(
                PutObjectArgs.builder()
                        .bucket(minioBucket)
                        .object(objectName)
                        .stream(inputStream, fileSize, -1)
                        .contentType(contentType)
                        .build());
    }
    /**
     * 获取MinIO文件路径
     * @param objectName 对象名称
     * @return MinIO文件路径
     */
    private String getMinioFilePath(String objectName) {
        return minioBucket + "/" + objectName;
    }

    /**
     * 获取内容类型
     * @param extension 文件扩展名
     * @return 内容类型
     */
    private String getContentType(String extension) {
        switch (extension.toLowerCase()) {
            case "pdf":
                return "application/pdf";
            case "xls":
                return "application/vnd.ms-excel";
            case "xlsx":
                return "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
            case "csv":
                return "text/csv";
            case "zip":
                return "application/zip";
            default:
                return "application/octet-stream";
        }
    }
}
